<!--
 * @description 瀑布流组件
 * @author: 陈陈
 * @date: 2025/05/09
 * @phone: 18560000860
 * @email: 18560000860@qq.com
 * @company: 济南晨霜信息技术有限公司 /
 * @business: 承接前后端项目的开发
-->
<template>
	<view
		class="pure-waterfall-item"
		:class="_classes"
		:style="_styles"
	>
		<slot></slot>
	</view>
</template>

<script>
	import commonComponentOptions from "../../config/options";
	export default {
		options: commonComponentOptions
	};
</script>

<script setup>
	import { ref, computed, onMounted, nextTick, getCurrentInstance, inject, watchEffect, onBeforeUnmount } from "vue";
	import props from "./props";
	import { getRect, generateUUID, delay } from "@/uni_modules/pure-utils";

	// -------------------------------------------------------------------------------- Refs
	// 向父组件添加子元素的函数
	const AddPureWaterfallChildrenDOM = inject("AddPureWaterfallChildrenDOM");
	// 删除父元素中的节点信息
	const DeletePureWaterfallChildrenDOM = inject("DeletePureWaterfallChildrenDOM");
	// 父元素计算出到布局信息
	const PureWaterfallChildrenRects = inject("PureWaterfallChildrenRects");
	// 列数
	const PureWaterfallCols = inject("PureWaterfallCols");
	// 间隔
	const PureWaterfallGap = inject("PureWaterfallGap");
	// 组件实例
	const _instance = getCurrentInstance();
	// uuid
	const _uuid = generateUUID();
	// 是否正在获取节点信息
	let _isGettingRect = false;
	// 等待更新节点信息的队列
	let _waitingUpdateRect = [];

	// -------------------------------------------------------------------------------- Props
	const _props = defineProps(props);

	// -------------------------------------------------------------------------------- Emits
	const _emits = defineEmits([]);

	// -------------------------------------------------------------------------------- Classes
	const _classes = computed(() => {
		const array = [];

		// uuid
		array.push(_uuid);

		// 是否已初始化
		if (_rect.value?.isInited) array.push("pure-waterfall-item--inited");

		return array;
	});

	// -------------------------------------------------------------------------------- Styles
	const _styles = computed(() => {
		const array = [];

		// top
		if (_rect?.value?.isInited) array.push(`top: ${_rect.value?.top || 0}px;`);
		else array.push(`top: 100%;`);

		// left
		array.push(
			`left: calc(var(--pure-waterfall-col-width) * ${_rect.value?.colIndex || 0} + var(--pure-waterfall-gap) * ${
				_rect.value?.colIndex || 0
			})`
		);

		// 加个delay效果
		// 随机0-50之间的整数
		array.push(`--pure-waterfall-animation-delay: ${Math.floor(Math.random() * 250)}ms;`);

		return array;
	});

	// 数据变化后更新节点信息
	watchEffect(() => {
		// 解构数组，不使用变量名，仅为触发依赖收集
		[_props.data, _props.index, _props.loaded, PureWaterfallCols.value, PureWaterfallGap.value];

		// 更新节点信息
		_getRect();
	});

	// 计算出到当前元素的布局信息
	const _rect = computed(() => {
		return PureWaterfallChildrenRects.value?.[_uuid];
	});

	// 组件加载后获取节点信息
	onMounted(() => {
		//  获取节点信息
		_getRect();
	});

	// 组件卸载前删除节点信息
	onBeforeUnmount(() => {
		// 删除父元素中的节点信息
		DeletePureWaterfallChildrenDOM(_uuid);
	});

	// 获取节点信息
	async function _getRect() {
		// 正在获取节点信息
		if (_isGettingRect) {
			// 将本地获取节点信息的任务添加到队列
			_waitingUpdateRect.push(1);
			return;
		}

		// 更新状态
		_isGettingRect = true;

		// 清空队列
		_waitingUpdateRect = [];

		// 等待数据渲染完成
		await nextTick();
		await delay(100);

		// 获取节点信息
		await getRect(`.${_uuid}`, _instance).then((data) => {
			// 将节点信息添加到父元素中
			AddPureWaterfallChildrenDOM({
				...data,
				uuid: _uuid,
				index: _props.index
			});
		});

		// 继续计算
		// 等待一下，节省一点性能
		await delay(100);

		// 更新状态
		_isGettingRect = false;

		// 如果队列不为空，则继续更新节点信息
		if (_waitingUpdateRect?.length > 0) _getRect();
	}
</script>

<style scoped lang="scss">
	@import "./style.scss";
</style>
